# cmake in linux

cmake_minimum_required(VERSION 3.20)
if(${CMAKE_VERSION} VERSION_LESS_EQUAL 3.20)
	cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
else()
	cmake_policy(VERSION 3.16)
endif()

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

project("etws-sxk2307")

set(BUILD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/bin)
message(STATUS "etws:${BUILD_DIR}")

set(targetName ETWS2307-SX-LINUX-V3R0-01-01)
set(targetExtensionName .elf)

string(TIMESTAMP COMPILE_TIME %y-%m-%d-%H:%M:%S) 
string(TIMESTAMP FILE_TIME %y%m%d)
set(buildTime    ${COMPILE_TIME}) 


set(debugSuffix _d)
set(targetFullName ${targetName}_${FILE_TIME}${targetExtensionName})
set(debugMacro ETWS_DEBUG)
if(NOT DEFINED Major OR Major STREQUAL "")
set(Major 3)
endif()
if(NOT DEFINED Minor OR Minor STREQUAL "")
set(Minor 0)
endif()
if(NOT DEFINED Patch OR Patch STREQUAL "")
set(Patch 0)
endif()



#获取年份后两位，使用 %Y 获取完整年份
string(TIMESTAMP TIME_YEAR %y)
set(buildYear ${TIME_YEAR})
#获取月份
string(TIMESTAMP TIME_MONTH %m)
set(buildMonth ${TIME_MONTH})
#获取日期
string(TIMESTAMP TIME_DAY %d)
set(buildDay ${TIME_DAY})
set(VersionConfigPath ${CMAKE_CURRENT_SOURCE_DIR}) #工程源码下的include目录


message("debug = " ${debug})
if (debug STREQUAL "ON" OR debug STREQUAL "on")
	set(targetFullName ${targetName}${debugSuffix}_${FILE_TIME}${targetExtensionName})
	set(extraCxxFlag "-D${debugMacro} -DMAJORVER=${Major} -DMINORVER=${Minor} -DPATCHVER=${Patch} -Wno-comment")
else()
	set(extraCxxFlag "-DMAJORVER=${Major} -DMINORVER=${Minor} -DPATCHVER=${Patch}")
endif()

project(${targetFullName}[C][C++])
message("project name: " ${PROJECT_NAME})
message(STATUS "binary file name: " ${targetFullName})
message("project root dir = " ${PROJECT_SOURCE_DIR})
set(PROJECT_BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/bin)

#需要在源码目录下创建VersionConfig.h.in和VersionConfig.h
configure_file( 
    "${VersionConfigPath}/Misc/VersionConfig.h.in"
    "${VersionConfigPath}/inc/VersionConfig.h"
)


# 定义easylogging支持线程安全的宏定义
add_definitions(-DELPP_THREAD_SAFE)
# add_definitions(-DELPP_UNICODE)


# 添加FFTW静态库路径
set(FFTW_ROOT ${CMAKE_SOURCE_DIR}//lib/fftw_static)
set(FFTW_INCLUDE_DIR ${FFTW_ROOT}/include)
set(FFTW_LIB_DIR ${FFTW_ROOT}/lib)

# set(ARCH arm64)
# ARCH ?= arm64
# CROSS_COMPILE   ?= aarch64-linux-gnu-


if(NOT DEFINED ARCH OR ARCH STREQUAL "")
	message(WARNING "host compile.")
	set(cCompilerPath    gcc)
	set(cxxCompilerPath  g++)
	set(CMAKE_SYSTEM_PROCESSOR x86_64) #设置目标处理器架构
else()
	message(WARNING "cross compile.")
	#set(crossCompilePath "/path/to/rootfs")
	set(CMAKE_CROSSCOMPILING TRUE)
	set(CMAKE_SYSTEM_PROCESSOR ${ARCH}) #设置目标处理器架构
	if(NOT DEFINED CROSS_COMPILE OR CROSS_COMPILE STREQUAL "")
		set(cCompilerPath    aarch64-linux-gnu-gcc)
		set(cxxCompilerPath	aarch64-linux-gnu-g++)
	else()
		set(cCompilerPath    ${CROSS_COMPILE}gcc)
		set(cxxCompilerPath  ${CROSS_COMPILE}g++)
	endif()
endif()

message(STATUS "cCompilerPath  "  ${cCompilerPath})
message(STATUS "cxxCompilerPath  "  ${cxxCompilerPath})


set(CMAKE_C_COMPILER    ${cCompilerPath})
set(CMAKE_CXX_COMPILER  ${cxxCompilerPath})
set(CMAKE_SYSTEM_NAME Linux)

# cross compile configuration.
# cmake .. -DsysRootfsPath:STRING=/path/to/rootfs -DCROSS_COMPILE:STRING=/path/to/gcc

set(CMAKE_SYSROOT ${sysRootfsPath})
set(CMAKE_FIND_ROOT_PATH  ${sysRootfsPath} ${SYSROOT_PATH})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM  NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY  ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE  ONLY)

set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH	
	"$ORIGIN" 
	"$ORIGIN/lib" 
	"$ORIGIN/../lib" 
	"$ORIGIN/../../lib" 
	
)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)

message(STATUS "cross compile rootfs root path: " ${sysRootfsPath})

set(prefix ${CMAKE_CURRENT_SOURCE_DIR})
message(prefix = ${prefix})

###############################################################################################################################################################################
set(includePath 
	${prefix}/inc 
	${prefix}/Conf 
	${prefix}/src/packetResolver 
	${prefix}/src/servoMotor  
	${prefix}/Middlewares/dataTransmission/fastDDS/idl 
	${prefix}/Middlewares/dataTransmission/fastDDS 
	${prefix}/Middlewares/dataTransmission/webTop 
	${prefix}/Middlewares/myLog 
	${prefix}/Middlewares/myLog/easylogging 
	${prefix}/Middlewares/myLog/easylogger/inc 
	${prefix}/Middlewares/Message 
	${prefix}/Middlewares/usrPort 
	${prefix}/src/dataShare 
	${prefix}/src/gnss  
	${FFTW_INCLUDE_DIR}  # 添加 FFTW 头文件目录

)

set(srcPath 
	${prefix}/src 
	${prefix}/src/Service 
	${prefix}/src/packetResolver 
	${prefix}/src/packetResolver/ddsCmdV1 
	${prefix}/src/packetResolver/sxkCmdV1 
	${prefix}/src/packetResolver/lxCmdV1 
	${prefix}/src/packetResolver/waveCmdV1 
	${prefix}/src/dataShare 
	${prefix}/src/Uio 
	${prefix}/src/Devices 
	${prefix}/src/Node 
	${prefix}/src/Heartbeat 
	${prefix}/src/servoMotor  
	${prefix}/Misc  
	${prefix}/Conf  
	${prefix}/src/gnss 

)

set(libSrcPath 
	# ${prefix}/src/Proto/FastDDS 

)

# Find requirements
find_package(fastcdr REQUIRED)
find_package(fastrtps 2.12 REQUIRED)


# 添加 FFTW 静态库目标
add_library(fftw3 STATIC IMPORTED)
set_target_properties(fftw3 PROPERTIES
    IMPORTED_LOCATION ${FFTW_LIB_DIR}/libfftw3.a
    INTERFACE_INCLUDE_DIRECTORIES ${FFTW_INCLUDE_DIR}
)

add_library(fftw3_threads STATIC IMPORTED)
set_target_properties(fftw3_threads PROPERTIES
    IMPORTED_LOCATION ${FFTW_LIB_DIR}/libfftw3_threads.a
)

set(libs 
	pthread 
	stdc++fs 
	ddsProtocol 
	dataResolver  
	myLog 
	Messages 
	webProtocol 
	uartProtocol 
	fftw3_threads  # 添加 FFTW 线程支持库
	fftw3  # 添加 FFTW 主库
    m  # 添加数学库（FFTW 需要）

) 


# 添加 OpenMP（如果 FFTW 配置了线程支持）
find_package(OpenMP)
if(OpenMP_C_FOUND)
    list(APPEND libs OpenMP::OpenMP_C)
endif()

link_directories( 
	${prefix}/lib 
	/usr/local/lib 
)

###############################################################################################################################################################################

set(projectBuildPath ${prefix}/build)
set(debugFileGeneratePath ${projectBuildPath}/debug)
set(releaseFileGeneratePath ${projectBuildPath}/release)

macro(checkDir dir)
	if(EXISTS ${dir})
		if(IS_DIRECTORY ${dir})
			message("directory \"${dir}\" already exists!")
		else()
			file(RENAME ${dir} ${dir}.old)
			file(MAKE_DIRECTORY ${dir})
			message("rename file ${dir} and create directory: ${dir}")
		endif()
	else()
		file(MAKE_DIRECTORY ${dir})
		message("create new directory: ${dir}")
	endif()
endmacro()

checkDir(${projectBuildPath})

message("project bin dir = " ${PROJECT_BINARY_DIR})
message("current file name: " ${CMAKE_CURRENT_LIST_FILE})
message("current line number: " ${CMAKE_CURRENT_LIST_LINE})

macro(addSuffix srcList suffix)
	foreach(tmp ${${srcList}})
		if(DEFINED tmpList)
			list(APPEND tmpList ${tmp}${suffix})
		else()
			set(tmpList ${tmp}${suffix})
		endif()
	endforeach()
	set(${srcList} ${tmpList})
	unset(tmpList)
	message(${${srcList}})
endmacro()

message("*****************************************************************************************")
if (debug STREQUAL "ON" OR debug STREQUAL "on")
	set(buildVersion debug) 
	# addSuffix(libs _d) 
	# set(librarySuffix _d) 
	checkDir(${debugFileGeneratePath})
	set(CMAKE_CXX_FLAGS "-g -O0 -std=c++${CMAKE_CXX_STANDARD} -v -Wl,--verbose -Wall -fPIC ${CMAKE_CXX_FLAGS} ${extraCxxFlag}")
else()
	set(buildVersion release)
	
	checkDir(${releaseFileGeneratePath})
	set(CMAKE_CXX_FLAGS "-std=c++${CMAKE_CXX_STANDARD} -Wall -O3 -fPIC ${CMAKE_CXX_FLAGS} ${extraCxxFlag}")
endif()

set(buildFileName ${buildVersion}/${buildVersion}_ETWS2307-SX-V${Major}R${Minor}_${FILE_TIME})
checkDir(${PROJECT_BINARY_DIR}/${buildFileName})

set(cfgFilePath ${PROJECT_BINARY_DIR}/${buildFileName}/cfg)
checkDir(${cfgFilePath})


message(WARNING "CXX Flag: " ${CMAKE_CXX_FLAGS})
message("build version: " ${buildVersion})
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/${buildFileName})
message("executable path: " ${EXECUTABLE_OUTPUT_PATH})
message("*****************************************************************************************")

# 设置全局变量给下级CMAKE
message(STATUS "Configuring GLOBAL EXECUTABLE_OUTPUT_PATH...")
set_property(GLOBAL PROPERTY BIN_DIR ${EXECUTABLE_OUTPUT_PATH})


# 添加子CMAKE
add_subdirectory(Middlewares/myLog)
add_subdirectory(Middlewares/usrPort)
add_subdirectory(Middlewares/dataTransmission/fastDDS)
add_subdirectory(Middlewares/dataTransmission/webTop)
add_subdirectory(Middlewares/dataTransmission/uartLite)
add_subdirectory(Middlewares/Message)

# src sub dir.
foreach(subDir ${srcPath})
	message("child source directory: " ${subDir})
	aux_source_directory(${subDir} srcFiles) 	#top cmake file's variable will be delivered to other sub cmake files,so we destroy it at the end int this CMake file.
endforeach(subDir ${srcPath})

foreach(item ${srcFiles})
	message("file ${item}")
endforeach(item ${srcFiles})

# src header sub dir.
include_directories(${includePath})

# lib src sub dir.
foreach(subDir ${libSrcPath})
	message("child library source directory: " ${subDir})
	add_subdirectory(${subDir})
endforeach(subDir ${libSrcPath})

add_executable(${targetFullName} ${srcFiles})
target_link_libraries(${targetFullName} ${libs})

file(COPY Doc/Config.ini DESTINATION ${cfgFilePath})
file(COPY Doc/mylog.conf DESTINATION ${cfgFilePath})
# INSTALL(DIRECTORY Doc/ DESTINATION ${cfgFilePath})

#other internal system information variables
message("CMAKE_MAJOR_VERSION = " ${CMAKE_MAJOR_VERSION})
message("CMAKE_MINOR_VERSION = " ${CMAKE_MINOR_VERSION})
message("CMAKE_PATCH_VERSION = " ${CMAKE_PATCH_VERSION})
message("CMAKE_SYSTEM = " ${CMAKE_SYSTEM})
message("CMAKE_SYSTEM_NAME = " ${CMAKE_SYSTEM_NAME})
message("CMAKE_SYSTEM_VERSION = " ${CMAKE_SYSTEM_VERSION})
message("CMAKE_SYSTEM_PROCESSOR = " ${CMAKE_SYSTEM_PROCESSOR})
message("UNIX = " ${UNIX})

unset(srcFiles)

